
#include "soc.h"
#include <stdarg.h>
#include "app_timer.h"
#include "nrf_drv_clock.h"


/**
 * TTL io port configuration and operation
 */
void Ttl_Io_Init( void )
{
    // pin gsm_power_on is p.05
    nrf_gpio_pin_clear( PIN_GSM_POWER_EN );
	nrf_gpio_cfg_output( PIN_GSM_POWER_EN );
    // pin gsm_power_on_key is p.30
    nrf_gpio_pin_clear( PIN_GSM_POWER_KEY );
    nrf_gpio_cfg_output( PIN_GSM_POWER_KEY);
    // led is p.14 p.13
    nrf_gpio_cfg_output( PIN_LED_RED );
    nrf_gpio_cfg_output( PIN_LED_BLUE );
    // GNSS ant power control
    nrf_gpio_cfg_output( PIN_GNSS_POWER_EN );

    // KEY1 and KEY2
    nrf_gpio_cfg_input( PIN_KEY1, NRF_GPIO_PIN_NOPULL );
    nrf_gpio_cfg_input( PIN_KEY2, NRF_GPIO_PIN_NOPULL );

    // Cam control
    nrf_gpio_cfg_output( PIN_CAM_EN );
	
	// hall power
	nrf_gpio_cfg_output( PIN_HALL_POWER );
	nrf_gpio_pin_set( PIN_HALL_POWER );
}

void Ttl_Io_Set( TTL_IO_T pin, uint8_t set )
{
    if( set ) {
        nrf_gpio_pin_set( pin );
    } else {
        nrf_gpio_pin_clear( pin );
    }
}

uint8_t Ttl_Io_Get( TTL_IO_T pin )
{
    return (uint8_t)nrf_gpio_pin_read( pin );
}

/**
 * UART 
 */
typedef struct line_fifo_t
{
    int8_t buff[UART_LINE_FIFO_MAX][UART_LINE_LENGTH_MAX];
    uint8_t start;
    uint8_t end;
} LINE_FIFO_T;
LINE_FIFO_T line_fifo =
{
    .start = 0,
    .end = 0,
};

static void line_fifo_put( int8_t * line )
{
    memcpy( line_fifo.buff[line_fifo.end], line, UART_LINE_LENGTH_MAX );
    line_fifo.end ++;
    if( line_fifo.end >= UART_LINE_FIFO_MAX ) {
        line_fifo.end = 0;
    }
}

static RET_TYPE_T line_fifo_get( int8_t * line )
{
    if( line_fifo.start == line_fifo.end ) {
        return RET_FAILED;
    }
    memcpy( line, line_fifo.buff[line_fifo.start], UART_LINE_LENGTH_MAX );
    line_fifo.start++;
    if( line_fifo.start >= UART_LINE_FIFO_MAX ) {
        line_fifo.start = 0;
    }
    return RET_OK;
}

static void uart_evt_handler(app_uart_evt_t * p_event)
{ 
    static int8_t data_array[UART_LINE_LENGTH_MAX];
    static uint32_t index = 0;

    switch (p_event->evt_type)
    {
        /**@snippet [Handling data from UART] */
        case APP_UART_DATA_READY:
						app_uart_get((uint8_t*)&data_array[index]);
            if ((data_array[index] == '\n')) {
								data_array[index+1] = 0;
                line_fifo_put( data_array );
								index = 0;
						} else {
                index++;
            }
			break;
        /**@snippet [Handling data from UART] */
        case APP_UART_COMMUNICATION_ERROR:
            APP_ERROR_HANDLER(p_event->data.error_communication);
            break;

        case APP_UART_FIFO_ERROR:
            APP_ERROR_HANDLER(p_event->data.error_code);
            break;

        default:
            break;
    }
}

void Uart_Init( void )
{
    uint32_t err_code;

    const app_uart_comm_params_t comm_params =
    {
        .rx_pin_no    = 3,
        .tx_pin_no    = 4,
        .rts_pin_no   = UART_PIN_DISCONNECTED,
        .cts_pin_no   = UART_PIN_DISCONNECTED,
        .flow_control = APP_UART_FLOW_CONTROL_DISABLED,
        .use_parity   = false,
        .baud_rate    = UART_BAUDRATE_BAUDRATE_Baud115200
    };

    APP_UART_FIFO_INIT(&comm_params,
                        256,
                        256,
                        uart_evt_handler,
                        APP_IRQ_PRIORITY_LOWEST,
                        err_code);

    APP_ERROR_CHECK(err_code);
}

void Uart_Send_Line( const int8_t *line, ... )
{
    static int8_t str_buff[UART_LINE_LENGTH_MAX];
    uint32_t idx;
    va_list args;
    va_start( args, line );
    vsprintf( (void *)(str_buff), (void *)line, args );
    va_end( args );
    idx = 0;
    while( str_buff[idx] != 0 ) {
        app_uart_put(str_buff[idx]);
        idx ++;
    }
}

RET_TYPE_T Uart_Get_Line( int8_t *line )
{
    return line_fifo_get( line );
}

/**
 * Timer
 */
extern void Control_Loop( void );
static void timer_handler(void * p_context)
{
//    static uint32_t counter=0;
    UNUSED_PARAMETER(p_context);
//    counter++;
//    if( counter%2 ) {
//        Ttl_Io_Set( PIN_LED_BLUE, 1 );
//    } else {
//        Ttl_Io_Set( PIN_LED_BLUE, 0 );
//    }
//	Ttl_Io_Set( PIN_LED_RED, Ttl_Io_Get( PIN_KEY1 ) );
//	Ttl_Io_Set( PIN_LED_BLUE, Ttl_Io_Get( PIN_KEY2 ) );
    Control_Loop();
}

static volatile uint8_t g_delay_flag;
static void delay_handler(void * p_context)
{
    g_delay_flag = 1;
}


#define TIMER_MS_TO_TICK(MS) (APP_TIMER_TICKS(100, 0) * (MS / 100))

APP_TIMER_DEF(g_timer_id);
APP_TIMER_DEF(g_delay_id);
void Timer_Init( )
{
    APP_TIMER_INIT(0, 2, NULL);
    app_timer_create(&g_timer_id, APP_TIMER_MODE_REPEATED, timer_handler);
    app_timer_create(&g_delay_id, APP_TIMER_MODE_SINGLE_SHOT, delay_handler);
    app_timer_start(g_timer_id, TIMER_MS_TO_TICK(100), NULL);
}

void Timer_Delay( uint32_t ms )
{
    g_delay_flag=0;
    app_timer_start(g_delay_id, TIMER_MS_TO_TICK(ms), NULL);
    while(!g_delay_flag) {
		//Ble_Power_Manage();
	}
}

/**
 * Soc common
 */
void Soc_Init( void )
{
	nrf_drv_clock_init();
    Ttl_Io_Init();
    Timer_Init();
	
}


